package com.zg.spring.cloud.alibaba.sentinel.controller;

import com.alibaba.csp.sentinel.AsyncEntry;
import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphO;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.CompletableFuture;

/**
 * 定义资源
 */
@RestController
public class ResourceController {

    @RequestMapping("/hello0")
    public String hello0(){
        return "hello0";
    }

    /**
     * 1、抛出异常的方式定义资源
     */
    @RequestMapping("/hello1")
    public String hello1(){
        // 资源名可使用任意有业务语义的字符串，比如方法名、接口名或其它可唯一标识的字符串。
        try (Entry entry = SphU.entry("hello1")) {
            // 被保护的业务逻辑
            // do something here...
            return "hello1";
        } catch (BlockException ex) {
            // 资源访问阻止，被限流或被降级
            // 在此处进行相应的处理操作
            return "网络繁忙，请稍后";
        }
    }


    /**
     * 2、返回布尔值方式定义资源
     */
    @RequestMapping("/hello2")
    public String hello2(){
        // 资源名可使用任意有业务语义的字符串
        if (SphO.entry("hello2")) {
            // 务必保证finally会被执行
            try {
                /**
                 * 被保护的业务逻辑
                 */
                return "hello2";
            } finally {
                SphO.exit();
            }
        } else {
            // 资源访问阻止，被限流或被降级
            // 进行相应的处理操作
            return "网络繁忙，请稍后";
        }
    }

    /**
     * 3、注解方式定义资源
     */
    @RequestMapping("/hello3")
    @SentinelResource(value = "333", blockHandler = "blockHandler", fallback = "fallback")
    public String hello3() {
        return "hello3";
    }

    public String blockHandler(BlockException exception){
        return "服务被限流";
    }

    public String fallback(RuntimeException exception){
        return "服务错误，请联系管理员";
    }

    /**
     * 4、异步调用支持
     */
    @RequestMapping("/hello4")
    public String hello4(){
        try {
            AsyncEntry entry = SphU.asyncEntry("hello4");

            // 异步调用.
            doAsync();
            return "hello4";
        } catch (BlockException ex) {
            // Request blocked.
            // Handle the exception (e.g. retry or fallback).
            return "网络繁忙，请稍后";
        }

    }

    public void doAsync(){
        CompletableFuture.runAsync(() -> {
            try {
                System.out.println("hello4");
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        });
    }


}
